#include "livetrackautosaver.h"
#include "livetrack.h"
#include "configuration.h"
#include "controls/ftmessagebox.h"



/*
    Autosave workflow....

    NOTE: AutosaveStart only when some data needs to be written on disk.
          The only exception is when user select "autosave on" from config. In this
          case a "presave" needs to be done in case the track is big and some time is required.

    Entry Points: constructor, change from config, loadTrack
    Exit Points: processQuit, destructor, loadTrack

    - on constructor check if there is an autosave already
       YES: ask the user if it has to be restored
            NO: delete the stale file and continue normally
           YES: recover the file. Keep the file if autosave enabled, otherwise delete the file.

    - When user change autosave from config...
        ENABLE: (from disabled) will precache autosave (overriding existing file if any)
       DISABLE: (from enabled) will stop autosave, delete autosave file

    - When loading track:
        (after saving is user want to save) after loading new track, preacahe autosave.
        Also remember to close the autosave BEFORE doing all this.

    - On quit/termination (with autosave on)
        DESTRUCTOR: close autosave file. Stop.
          ASK_QUIT: if track is modified and user want to save
                NO: delete autosave file
               YES: stop autosave. save GPX and if save is ok, remove autofile file.

*/

LiveTrackAutosaver::LiveTrackAutosaver() :
   QObject()
{
    autosave = configuration->livetrackAutosave();
    connect( configuration, SIGNAL(livetrackAutosaveChanged(bool)),
             this, SLOT(updateAutosave(bool)) );
    keepAutosave = false;
}

LiveTrackAutosaver::~LiveTrackAutosaver()
{
    if ( !keepAutosave )
    {
        autosave_file.remove();
    }
}

bool LiveTrackAutosaver::initialize(LiveTrack * lt )
{
    bool ret = false;
    livetrack = lt;
    autosave_file.setFileName( configuration->defaultPath() + "\\autosave.twt" );

    // Check autosave and ask if user wants to reload or delete it
    if ( autosave_file.exists() )
    {
        if ( FTMessageBox::Yesno(tr("Unsaved Live Track found"),
                                 tr("Reload last Live Track?"),
                                 tr("Reload"),
                                 tr("Delete") ) )
        {
            if ( autosave_file.open(QIODevice::ReadOnly | QIODevice::Text))
            {
                WorkerAutoLoad wal( &autosave_file, livetrack );
                ret = wal.run();
                autosave_file.close();
            }

            if ( !autosave )
                autosave_file.remove();
        }
        else
            autosave_file.remove();
    }
    return ret;
}

bool LiveTrackAutosaver::AutosaveEnabled() const
{
    return autosave;
}

void LiveTrackAutosaver::updateAutosave(bool a)
{
    // REMEMBER: this is called ONLY when the user enables/disable the AUTOSAVE from configuration...
    if ( a != autosave )
    {
        // Stop autosave?
        if ( a == false )
        {   // Stop autosaving
            AutosaveStop();
        }
        else // Start autosave?
        {
            // Precache current LiveTrack to file...
            AutosavePrecache();
        }
        autosave = a;
    }
}

bool LiveTrackAutosaver::AutosaveStart()
{   // Not autosaving? just quit.
    if ( !autosave )
        return false;

    // If file is already open, return ok.
    if ( !autosave_file.isOpen() )
    {   // Does the file already exists? (this should ALWAYS be the case)
        if ( autosave_file.exists() )
            return autosave_file.open( QIODevice::Append | QIODevice::Text );
        else // This is not good... why are we here??? Well, just create a new one, but???????
            return autosave_file.open( QIODevice::WriteOnly | QIODevice::Text );
    }
    return true;
}

void LiveTrackAutosaver::AutosaveStop()
{
    // Close autosave if open...
    if ( autosave_file.isOpen() )
        autosave_file.close();
    // and remove file, if any!
    if ( autosave_file.exists() )
        autosave_file.remove();
}

QString LiveTrackAutosaver::formatBacktrack(int leg_id)
{
    return QString("%1 %2\n").arg(AS_BACK_SEP)
                             .arg(leg_id);
}

QString LiveTrackAutosaver::formatPoint(int leg_id, const GPS_point* pt)
{
    return QString("%1 %2 %3\n").arg(AS_POINT_SEP)
                                .arg( leg_id )
                                .arg( pt->serialize() );
}

QString LiveTrackAutosaver::formatWaypoint(const GPS_waypoint* wp)
{
    return QString("%1 %2 %3\n").arg( AS_WAYPOINT_SEP )
                             .arg( wp->id() )
                             .arg( wp->serialize() );
}

QString LiveTrackAutosaver::formatLeg(const GPS_leg* lg )
{
    return QString("%1 %2 %3\n").arg(AS_LEG_SEP)
                             .arg( lg->id() )
                             .arg( lg->serialize() );
}

QString LiveTrackAutosaver::formatTitle(const QString& t)
{
    return QString(AS_TITLE_SEP) + '"' + t.toAscii().toBase64() + "\"\n";
}

QString LiveTrackAutosaver::formatDescription(const QString& d)
{
    return QString(AS_DESC_SEP) + '"' + d.toAscii().toBase64() + "\"\n";
}

QString LiveTrackAutosaver::formatActiveLeg(int l)
{
    return QString("%1 %2\n").arg( AS_ACTIVE_LEG_SEP )
                             .arg( l );
}

QString LiveTrackAutosaver::formatDeleteLeg(int l)
{
    return QString("%1 %2\n").arg( AS_DELETE_LEG_SEP )
                             .arg( l );
}

QString LiveTrackAutosaver::formatDeleteWaypoint(int l)
{
    return QString("%1 %2\n").arg(AS_DELETE_WAYPOINT_SEP)
                             .arg( l );
}

QString LiveTrackAutosaver::formatFilename(const QString& t )
{
    return QString(AS_FILENAME_SEP)+ '"' + t.toAscii().toBase64() + "\"\n";
}


void LiveTrackAutosaver::AutosaveBacktrack(int leg_id)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << LiveTrackAutosaver::formatBacktrack( leg_id );
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveTitle(const QString& t)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << LiveTrackAutosaver::formatTitle(t);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveFilename(const QString& t)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatFilename(t);
    }
}

void LiveTrackAutosaver::AutosaveDescription(const QString& d)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatDescription(d);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveActiveLeg(int l)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatActiveLeg(l);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveDeleteLeg(int l)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatDeleteLeg(l);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveDeleteWaypoint(int l)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatDeleteWaypoint(l);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosavePoint( int leg_id, const GPS_point* pt)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatPoint(leg_id, pt);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveWaypoint( const GPS_waypoint* wp)
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatWaypoint(wp);
        keepAutosave = true;
    }
}

void LiveTrackAutosaver::AutosaveLeg(const GPS_leg * lg )
{
    if ( AutosaveStart() )
    {
        QTextStream stream(&autosave_file);
        stream << formatLeg(lg);
        keepAutosave = true;
    }
}

GPS_point* LiveTrackAutosaver::readPoint(QTextStream& stream, int &leg_id)
{
    stream >> leg_id;
    return GPS_point::unserialize( stream );
}

GPS_waypoint* LiveTrackAutosaver::readWaypoint(QTextStream & stream, GPS_waypoint *wp)
{
    if ( wp == NULL )
        wp = new GPS_waypoint();
    GPS_waypoint::unserialize( stream, wp );
    return wp;
}

GPS_leg* LiveTrackAutosaver::readLeg(QTextStream & stream, GPS_leg *leg)
{
    if ( leg == NULL )
        leg = new GPS_leg();
    GPS_leg::unserialize( stream, leg );
    return leg;
}

QString LiveTrackAutosaver::readString(QTextStream& stream )
{
    QByteArray str;
    stream >> str;
    str.chop(1);
    str = str.mid(1);
    return QByteArray::fromBase64( str );
}

int LiveTrackAutosaver::readId(QTextStream & stream)
{
    int id;
    stream >> id;
    return id;
}

void LiveTrackAutosaver::AutosavePrecache()
{
    if ( !autosave )
        return;

    // Start by closing and deleting the autosave...
    AutosaveStop();
    if ( autosave_file.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text ) )
    {
        WorkerAutoSave was( &autosave_file, livetrack );
        was.run();
        autosave_file.close();
    }
}
